package org.txazo.blog.web.filter;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.txazo.blog.util.HttpUtil;
import org.txazo.blog.util.md5.MD5;

/**
 * ETag过滤器
 * 
 * @author Tu XiaoZhou
 * @since 2013-08-10
 * 
 */
public class JspETagFilter implements Filter {

	public static final String ETAG_FLAG_BEGIN = "ETag/\"";
	public static final String ETAG_FLAG_END = "\"";
	public static final String ETAG = "ETag";
	public static final String IF_NONE_MATCH = "If-None-Match";
	public static final String LAST_MODIFIED = "Last-Modified";

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;

		String uri = request.getServletPath();

		if (HttpUtil.isDynamicRequestOfURI(uri)) {
			if (uri.equals("/authCode.jsps")) {
				chain.doFilter(req, resp);
			} else {
				ByteArrayOutputStream buffer = new ByteArrayOutputStream();
				ETagResponseWrapper wrappedResponse = new ETagResponseWrapper(
						response, buffer);
				chain.doFilter(req, wrappedResponse);
				wrappedResponse.flushBuffer();

				byte[] bytes = buffer.toByteArray();

				String etag = ETAG_FLAG_BEGIN + MD5.md5(bytes) + ETAG_FLAG_END;
				String preETag = request.getHeader(IF_NONE_MATCH);

				response.setHeader(ETAG, etag);
				if (preETag != null && preETag.equals(etag)) {
					response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
				} else {
					response.setDateHeader(LAST_MODIFIED,
							System.currentTimeMillis());

					ServletOutputStream outputStream = response
							.getOutputStream();
					outputStream.write(bytes);
					outputStream.flush();
					outputStream.close();
				}
			}
		} else {
			chain.doFilter(req, resp);
		}
	}

	@Override
	public void destroy() {
	}

}
